package com.thingsgrid.firmware.service.impl;

import com.thingsgrid.device.entity.Device;
import com.thingsgrid.device.entity.Product;
import com.thingsgrid.firmware.entity.Firmware;
import com.thingsgrid.firmware.service.FirmwareVersionService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.LookupOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
@AllArgsConstructor
@SuppressWarnings("unchecked")//对应一个waring问题
public class FirmwareVersionServiceImpl implements FirmwareVersionService {

	@Autowired
	private MongoTemplate mongoTemplate;

	//接口方法实现
	/**
	 * 查询条件所属类型下拉菜单
	 */
	// 查询条件和张贺的，我的拓扑的，陈学东的重复，要不要改为一个
	//以下三个注解和拓扑一样，就不重复写了
	@Override
	public List GetProductTypeList() {
		List<Product> productList = QueryAllProductList();
		List<String> productTypeList = GetProductTypeListByproductList(productList);
		List<String> productTypeIdList = ListDeDuplicate(productTypeList);
		List<Map> list =new ArrayList<>();
		for(String oneProductType : productTypeIdList){
			Map<String, String> map = new HashMap<>();
			map.put("value",oneProductType);
			map.put("label",oneProductType);
			list.add(map);
		}
		return list;
	}
	/**
	 *查询条件产品名称下拉菜单
	 * productTypeId是前一个项的返回值
	 */
	@Override
	public List GetProductNameList(String productTypeId) {
		List<Product> productList = QueryProductListByProductTypeId(productTypeId);
		List<String> productNameList = GetProductNameListByproductList(productList);
		List<Map> list = new ArrayList<>();
		for (String oneProductName : productNameList){
			Map<String, String> map = new HashMap<>();
			map.put("value",oneProductName);
			map.put("label",oneProductName);
			list.add(map);
		}
		return list;
	}
	/**
	 *查询条件固件名称下拉菜单
	 * productName是前一个项的返回值
	 */
	@Override
	public List GetFirmwareNameList(String productName) {
		List<Map> list = new ArrayList<>();
		List<Product> productList = QueryProductByProductName(productName);
		for (Product oneProduct : productList){
			List<Firmware> firmwareList = QueryFirmwareListByProductId(oneProduct.getProductId());
			List<String> firmwareNameList = GetFirmwareNameListByFirmwareList(firmwareList);
			for (String oneFirmwareName : firmwareNameList){
				Map<String, String> map = new HashMap<>();
				map.put("value",oneFirmwareName);
				map.put("label",oneFirmwareName);
				list.add(map);
			}
		}
		return list;
	}
	/**
	 *根据查询条件查询固件表
	 */
	//只使用了产品和固件表，使用聚合查询加分页，更改返回值可以在field中添加
	@Override
	public Map<String, Object> QueryFirmwareListByCondition(String productType, String productName, String firmwareName, int current, int pageSize){
		LookupOperation lookupOperation = LookupOperation.newLookup()
			.from("product")
			.localField("product_id")
			.foreignField("product_id")
			.as("p");
		Criteria criteria =new Criteria();
		if(!(firmwareName == null || firmwareName.equals(""))){
			criteria.and("firmware_name").is(firmwareName);
		}else if(!(productName == null || productName.equals(""))){
			criteria.and("p.product_name").is(productName);
		}else if(!(productType == null || productType.equals(""))){
			criteria.and("p.product_type_id").is(productType);
		}
		criteria.and("p.is_publish").is(1);
		AggregationOperation match = Aggregation.match(criteria);
		AggregationOperation unwind = Aggregation.unwind("p");
		AggregationOperation project = Aggregation.project("firmware_id", "firmware_name", "firmware_version", "p.product_name", "create_time", "describe", "stats", "firmware_sign", "product_id").andExclude("_id");
		AggregationOperation limit = Aggregation.limit(pageSize);
		AggregationOperation skip = Aggregation.skip((long)((current-1)*pageSize));
		Aggregation aggregation = Aggregation.newAggregation(lookupOperation,unwind, match, project, skip, limit);
		AggregationResults<Map> aggregationResults =mongoTemplate.aggregate(aggregation, "firmware",Map.class);
		for (Map<String,Object> oneMap : aggregationResults){
			if(oneMap.get("stats").equals(1)){
				oneMap.put("stats","已验证");
			}else{
				oneMap.put("stats","未验证");
			}
			System.out.println(oneMap.get("stats"));
		}
		Aggregation noskipaggregation = Aggregation.newAggregation(lookupOperation, match, project);
		int total = mongoTemplate.aggregate(noskipaggregation,"firmware",Map.class).getMappedResults().size();
		Map<String,Object> map= new HashMap<>();
		map.put("total",total);
		map.put("list",aggregationResults.getMappedResults());
		return  map;
	}
	/**
	 *在固件表中新增固件
	 */
	@Override
	public int AddNewFirmware(String firmwareName, String firmwareVersion, String productName, String firmwareSign, String describe, String firmwareFile){
		String productId = QueryProductIdByProductName(productName);
		if(QueryFirmwareByFirmwareVersionAndProductId(firmwareVersion,productId)){
			Firmware firmware = new Firmware();
			String id = UUID.randomUUID().toString();
			firmware.setFirmwareId(id);
			firmware.setFirmwareName(firmwareName);
			firmware.setFirmwareVersion(firmwareVersion);
			firmware.setProductId(productId);
			firmware.setFirmwareSign(firmwareSign);
			firmware.setDescribe(describe);
			firmware.setFirmwareFile(firmwareFile);
			SimpleDateFormat today = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
			firmware.setCreateTime(today.format(new Date()));
			firmware.setStats(0);
			firmware.setUpgradeType(0);//升级方式怎么确定
			try{
				SaveFirmware(firmware);
			}catch (Exception e){
				return 3;
			}
			return 1;
		}else {
			return 2;
		}

	}
	/**
	 *固件删除
	 */
	@Override
	public boolean DelFirmwareList(String firmwareId){
		Query query=new Query(Criteria.where("firmware_id").is(firmwareId));
		try {
			mongoTemplate.remove(query, Firmware.class,"firmware");
		}catch (Exception e){
			return false;
		}
		return true;
	}
	/**
	 *固件验证中设备名称下拉菜单，
	 * productId为固件所属产品
	 */
	@Override
	public List GetdeviceNameList(String productId){
		List<Map> list = new ArrayList<>();
		List<Device> deviceList = QueryDeviceListByProductId(productId);
		List<String> deviceNameList = GetDeviceNameListByDeviceList(deviceList);
		for (String oneDeviceName : deviceNameList){
			Map<String, String> map = new HashMap<>();
			map.put("value",oneDeviceName);
			map.put("label",oneDeviceName);
			list.add(map);
		}
		return list;
	}
	/**
	 *固件验证
	 * 改变固件表中升级方式和验证状态
	 */
	@Override
	public boolean UpdateStats(String firmwareId, int upgradeType){
		Query query= new Query(Criteria.where("firmware_id").is(firmwareId));
		Update update = Update.update("stats",1);
		update.set("upgrade_type",upgradeType);
		try {
			mongoTemplate.updateFirst(query,update,"firmware");
		}catch (Exception e){
			return false;
		}
		return true;
	}
	/**
	 *新增固件中选择所属产品的下拉菜单
	 */
	@Override
	public List GetAllProductNameList(){
		List<Product> productList = QueryAllProductList();
		List<String> productNameList = GetProductNameListByproductList(productList);
		List<Map> list =new ArrayList<>();
		for(String oneProductName : productNameList){
			Map<String, String> map = new HashMap<>();
			map.put("value",oneProductName);
			map.put("label",oneProductName);
			list.add(map);
		}
		return list;
	}
	//调用到的方法

	/**
	 * 根据产品列表获得产品类型列表
	 */
	private List<String> GetProductTypeListByproductList(List<Product> productList) {
		List<String> productTypeList = new ArrayList<>();
		for (Product product : productList) {
			productTypeList.add(product.getProductTypeId());
		}
		return productTypeList;
	}
	/**
	 * 根据设备列表获得设备名称列表
	 */
	private List<String> GetDeviceNameListByDeviceList(List<Device> deviceList){
		List<String> deviceNameList = new ArrayList<>();
		for (Device device : deviceList) {
			deviceNameList.add(device.getDeviceName());
		}
		return deviceNameList;
	}
	//去重
	private List<String> ListDeDuplicate(List<String> oneList) {
		HashSet<String> h = new HashSet<>(oneList);
		oneList.clear();
		oneList.addAll(h);
		return oneList;
	}
	/**
	 * 根据产品列表获得产品名称列表
	 */
	private List<String> GetProductNameListByproductList(List<Product> productList) {
		List<String> productNameList = new ArrayList<>();
		for (Product product : productList) {
			productNameList.add(product.getProductName());
		}
		return productNameList;
	}
	/**
	 * 根据固件列表获得固件名称列表
	 */
	private List<String> GetFirmwareNameListByFirmwareList(List<Firmware> firmwareList) {
		List<String> firmwareNameList = new ArrayList<>();
		for (Firmware oneFirmware : firmwareList) {
			String deviceName = oneFirmware.getFirmwareName();
			firmwareNameList.add(deviceName);
		}
		return firmwareNameList;
	}

	// 查询语句
	private List<Product> QueryAllProductList() {
		Query query = new Query(Criteria.where("is_publish").is(1));
		return mongoTemplate.find(query,Product.class, "product");
	}

	private List<Product> QueryProductListByProductTypeId(String productTypeId) {
		Criteria criteria = new Criteria();
		criteria.and("product_type_id").is(productTypeId);
		criteria.and("is_publish").is(1);
		Query query = new Query(criteria);
		return mongoTemplate.find(query, Product.class, "product");
	}

	private List<Product> QueryProductByProductName(String productName) {
		Criteria criteria = new Criteria();
		criteria.and("product_name").is(productName);
		criteria.and("is_publish").is(1);
		Query query = new Query(criteria);
		return mongoTemplate.find(query, Product.class, "product");

	}
	private String QueryProductIdByProductName(String productName){
		Criteria criteria = new Criteria();
		criteria.and("product_name").is(productName);
		criteria.and("is_publish").is(1);
		Query query = new Query(criteria);
		Product product = mongoTemplate.findOne(query, Product.class, "product");
		if (product != null){
			return product.getProductId();
		}else {
			return "";
		}
	}
	private List<Device> QueryDeviceListByProductId(String productId){
		Criteria criteria = new Criteria();
		criteria.and("productId").is(productId);
		criteria.and("stats").is(1);
		criteria.and("start_stats").is(1);
		Query query = new Query(criteria);
		return mongoTemplate.find(query, Device.class, "device");

	}

	private List<Firmware> QueryFirmwareListByProductId(String productId) {
		Query query = new Query(Criteria.where("productId").is(productId));
		return mongoTemplate.find(query, Firmware.class, "firmware");
	}

	private void SaveFirmware(Firmware firmware){
		mongoTemplate.insert(firmware, "firmware");
	}

	private boolean QueryFirmwareByFirmwareVersionAndProductId(String firmwareVersion,String productId){
		Criteria criteria = new Criteria();
		criteria.and("product_id").is(productId);
		criteria.and("firmware_version").is(firmwareVersion);
		Query query = new Query(criteria);
		Firmware firmware = mongoTemplate.findOne(query, Firmware.class, "firmware");
		if(firmware == null){
			return true;
		}else{
			return false;
		}
	}

}
